home *** CD-ROM | disk | FTP | other *** search
Text File | 1990-01-28 | 30.5 KB | 1,051 lines |
- Newsgroups: comp.sources.misc
- organization: Eindhoven University of Technology, The Netherlands
- keywords: agetty2
- subject: v10i050: agetty, SYSV getty for dial-in lines
- from: wietse@wzv.win.tue.nl (Wietse Z. Venema)
- Sender: allbery@uunet.UU.NET (Brandon S. Allbery - comp.sources.misc)
-
- Posting-number: Volume 10, Issue 50
- Submitted-by: wietse@wzv.win.tue.nl (Wietse Z. Venema)
- Archive-name: agetty2
-
- This is a SYSV getty replacement with useful features for dial-in lines.
-
- The program adjusts the tty modes to parity bits, and to erase, kill and
- end-of-line characters found while reading a login name. The baud rate
- of incoming calls can be established by BREAK character processing or by
- parsing status messages produced by multi-speed Hayes-compatible modems.
-
- The first release of this program appeared december 1989. The main new
- feature introduced here is selective processing of the /etc/issue file.
-
- #! /bin/sh
- # This is a shell archive. Remove anything before this line, then unpack
- # it by saving it into a file and typing "sh file". To overwrite existing
- # files, type "sh file -c". You can also feed this as standard input via
- # unshar, or by typing "sh <file", e.g.. If this archive is complete, you
- # will see the following message at the end:
- # "End of shell archive."
- # Contents: README agetty.c agetty.8 Makefile
- # Wrapped by wietse@wzv on Sun Jan 28 17:56:42 1990
- PATH=/bin:/usr/bin:/usr/ucb ; export PATH
- if test -f 'README' -a "${1}" != "-c" ; then
- echo shar: Will not clobber existing file \"'README'\"
- else
- echo shar: Extracting \"'README'\" \(440 characters\)
- sed "s/^X//" >'README' <<'END_OF_FILE'
- X@(#) README 1.4 1/28/90 17:53:02
- X
- XThis is a SYSV getty replacement with useful features for dial-in lines.
- X
- XThe program adjusts the tty modes to parity bits, and to erase, kill and
- Xend-of-line characters found while reading a login name. The baud rate
- Xof incoming calls can be established by BREAK character processing or by
- Xparsing status messages produced by multi-speed Hayes-compatible modems.
- X
- X Wietse Venema (wietse@wzv.win.tue.nl)
- END_OF_FILE
- if test 440 -ne `wc -c <'README'`; then
- echo shar: \"'README'\" unpacked with wrong size!
- fi
- # end of 'README'
- fi
- if test -f 'agetty.c' -a "${1}" != "-c" ; then
- echo shar: Will not clobber existing file \"'agetty.c'\"
- else
- echo shar: Extracting \"'agetty.c'\" \(22691 characters\)
- sed "s/^X//" >'agetty.c' <<'END_OF_FILE'
- X/*++
- X/* NAME
- X/* agetty 8
- X/* SUMMARY
- X/* alternative System-V getty for dial-up lines
- X/* SYNOPSIS
- X/* agetty [-a alternate_rates] [-h] [-i] [-m] [-t timeout] port baud_rate
- X/* DESCRIPTION
- X/* \fIagetty\fR opens a tty port, prompts for a login name and invokes the
- X/* /bin/login command. It is normally invoked by \fIinit(8)\fR.
- X/*
- X/* \fIagetty\fR has some useful features for dial-up lines that are
- X/* not present in the System V Release 2 getty command:
- X/* .IP o
- X/* Adapts the tty settings to parity bits and to
- X/* erase, kill and end-of-line characters found in its input. The
- X/* program understands 7-bit characters with even, odd, none or space
- X/* parity, and 8-bit characters with no parity. The following special
- X/* characters are recognized: @ and Control-U (kill); #, DEL and
- X/* back space (erase); carriage return and line feed (end of line).
- X/* .IP o
- X/* Optionally recognizes the baud rate of incoming calls from the
- X/* status messages produced by some multi-speed Hayes-compatible modems.
- X/* .IP o
- X/* Optionally does not display the contents of the \fI/etc/issue\fR file.
- X/* .PP
- X/* This program does not use the \fI/etc/gettydefs\fR file. Except for
- X/* differences described in the documentation, the program appears to
- X/* operate similar to the System-V Release 2 \fIgetty\fR program.
- X/*
- X/* Options:
- X/* .TP
- X/* -a alternate_rates
- X/* Initially the program will use the \fIbaud_rate\fR as specified.
- X/* Upon receipt of successive BREAK characters the program will step
- X/* through the \fIalternate_rates\fR, which should be specified as a
- X/* comma-separated list (preferably in decreasing order). After all
- X/* \fIalternate_rates\fR have been tried, \fIagetty\fR will try the
- X/* speed specified with the \fIbaud_rate\fR argument and so on.
- X/* .TP
- X/* -h
- X/* Do not hang up the line. Normally, \fIagetty\fR will lower
- X/* DTR for two seconds to force a modem to hang up (if the hangup
- X/* feature has been compiled into the program).
- X/* .TP
- X/* -i
- X/* Do not display the contents of \fI/etc/issue\fR before writing the
- X/* login prompt. Terminals or computer programs may become confused
- X/* when receiving lots of text at the wrong baud rate; dial-up scripts
- X/* may fail if the login prompt is preceded by too much text.
- X/* .TP
- X/* -m
- X/* Try to extract the baud rate of incoming calls from the status message
- X/* produced by some multi-speed Hayes-compatible modems. These usually
- X/* produce a status message of the form: "<junk><speed><junk>".
- X/* If no \fIspeed\fR is found within one second, the \fIbaud_rate\fR as
- X/* specified on the command line will be used. Since the \fI-m\fR feature
- X/* will work only on lightly-loaded systems, you will probably want to use
- X/* it in combination with the \fI-a\fR option.
- X/* .TP
- X/* -t timeout
- X/* Causes the program to terminate if no user name could be read
- X/* within \fItimeout\fR seconds. This is useful only for dial-in lines.
- X/* EXAMPLES
- X/* For hard-wired lines:
- X/* .ti +5
- X/* /etc/agetty ttyM0 9600
- X/*
- X/* For dial-in lines with a 300/1200/2400 baud multi-speed modem:
- X/* .ti +5
- X/* /etc/agetty -t60 -m -a1200,300 ttyM1 2400
- X/* FILES
- X/* /etc/utmp, the system log file.
- X/* /etc/issue, printed before the login prompt.
- X/* /dev/console, problem reports.
- X/* BUGS
- X/* The baud-rate detection code (the \fI-m\fR option) only works if
- X/* \fIagetty\fR is scheduled soon enough after completion of a dial-in
- X/* call (within 30 ms with modems that talk at 2400 baud). For robustness,
- X/* always use the \fI-m\fR option in combination with the \fI-a\fR option.
- X/*
- X/* The contents of the /etc/issue file and the login prompt are always
- X/* output with space parity.
- X/* DIAGNOSTICS
- X/* All diagnostics are written to the console device. Error messages are
- X/* produced if the \fIport\fR argument does not specify a terminal; if
- X/* there is no /etc/utmp entry for the current process; and so on.
- X/* AUTHOR(S)
- X/* W.Z. Venema <wietse@wzv.win.tue.nl>
- X/* Eindhoven University of Technology
- X/* Department of Mathematics and Computer Science
- X/* Den Dolech 2, P.O. Box 513, 5600 MB Eindhoven, The Netherlands
- X/* CREATION DATE
- X/* Sat Nov 25 22:51:05 MET 1989
- X/* LAST MODIFICATION
- X/* 90/01/28 17:53:06
- X/* VERSION/RELEASE
- X/* 1.26
- X/*--*/
- X
- X#ifndef lint
- Xstatic char sccsid[] = "@(#) agetty.c 1.26 1/28/90 17:53:06";
- X#endif
- X
- X#include <termio.h>
- X#include <signal.h>
- X#include <sys/types.h>
- X#include <sys/stat.h>
- X#include <varargs.h>
- X#include <ctype.h>
- X#include <utmp.h>
- X
- X /*
- X * Things you may want to modify.
- X *
- X * HANGUP should be defined only if your tty driver is not able to hang up the
- X * modem (by briefly dropping DTR). If HANGUP is defined you probably cannot
- X * use the auto-baud and time-out features.
- X *
- X * If ISSUE is not defined, agetty will never display the contents of the
- X * /etc/issue file. You will not want to spit out large "issue" files at the
- X * wrong baud rate.
- X *
- X * You may disagree with the default line-editing etc. characters defined
- X * below. Note, however, that DEL cannot be used for interrupt generation
- X * and for line editing at the same time.
- X */
- X
- X#define ISSUE "/etc/issue" /* shown before login prompt */
- X
- X#define LOGIN "login: " /* login prompt */
- X
- X/* #define HANGUP /* enable hangup code */
- X
- X/* Some shorthands for control characters */
- X
- X#define CTL(x) (x ^ 0100) /* Assumes ASCII dialect */
- X#define CR CTL('M') /* carriage return */
- X#define NL CTL('J') /* line feed */
- X#define BS CTL('H') /* back space */
- X#define DEL CTL('?') /* delete */
- X
- X/* Defaults for line-editing etc. characters; you may want to change this */
- X
- X#define DEF_INTR CTL('C') /* default interrupt character */
- X#define DEF_QUIT CTL('\\') /* default quit char */
- X#define DEF_KILL CTL('U') /* default kill char */
- X#define DEF_EOF CTL('D') /* default EOF char */
- X#define DEF_SWITCH CTL('^') /* default switch char */
- X#define DEF_ERASE BS /* default erase char, see below */
- X#define DEF_EOL 0
- X
- X /*
- X * This program does not need the standard-i/o library. This keeps the
- X * executable small; useful for systems that do not have shared libaries
- X * (Sys-V Rel <3).
- X */
- X
- X#define BUFSIZ 1024
- X
- X/* Storage for command-line options */
- X
- X#define MAXSPEED 10
- X
- Xstruct options {
- X int flags; /* toggle switches, see below */
- X int timeout; /* time-out period */
- X int numspeed; /* number of baud rates to try */
- X int curspeed; /* current speed */
- X int speeds[MAXSPEED]; /* baud rates to be tried */
- X char *tty; /* name of tty */
- X};
- X
- X#define F_PARSE (1<<0) /* process modem status messages */
- X#define F_HANGUP (1<<1) /* hangup line */
- X#define F_ISSUE (1<<2) /* display /etc/issue */
- X
- X/* Storage for things detected while the login name was read */
- X
- Xstruct chardata {
- X int erase; /* erase character */
- X int kill; /* kill character */
- X int eol; /* end-of-line character */
- X int parity; /* what parity did we see */
- X int capslock; /* upper case without lower case */
- X};
- X
- X/* The following is used for understandable diagnostics */
- X
- Xextern int errno;
- Xextern char *sys_errlist[];
- Xstatic char *progname;
- Xextern char *strcpy();
- Xextern char *strcat();
- X
- X/* ... */
- X
- Xmain(argc, argv)
- Xint argc;
- Xchar **argv;
- X{
- X char *logname; /* login name, given to /bin/login */
- X char *get_logname();
- X struct chardata chardata; /* set by get_logname() */
- X struct termio termio; /* terminal mode bits */
- X static struct options options = {
- X F_HANGUP | F_ISSUE, /* hangup line and show /etc/issue */
- X 0, /* no timeout */
- X 1, /* no alternate baud rates */
- X 0, /* no alternate baud rates */
- X };
- X
- X progname = argv[0];
- X
- X /* Parse command-line arguments */
- X
- X parse_args(argc, argv, &options);
- X
- X /* Update the utmp file */
- X
- X update_utmp(options.tty);
- X
- X /* Open the tty as standard { input, output, error } */
- X
- X open_tty(options.tty, &termio);
- X
- X /* Optionally hang up the tty */
- X
- X if (options.flags & F_HANGUP)
- X hangup_tty(&termio);
- X
- X /* Initialize the termio settings (raw mode, eight-bit, blocking i/o) */
- X
- X termio_init(&termio, options.speeds[0]);
- X
- X /* Optionally detect the baud rate from the modem status message */
- X
- X if (options.flags & F_PARSE)
- X auto_baud(&termio);
- X
- X /* With dial-in lines, briefly pause to allow modems etc. to settle */
- X
- X if (options.timeout)
- X (void) sleep(1);
- X
- X /* Optional time-out feature */
- X
- X if (options.timeout)
- X (void) alarm((unsigned) options.timeout);
- X
- X /* Read the login name */
- X
- X while ((logname = get_logname(&options, &chardata, &termio)) == 0)
- X next_speed(&termio, &options);
- X
- X /* Disable time-out feature */
- X
- X if (options.timeout)
- X (void) alarm(0);
- X
- X /* Finalize the termio settings */
- X
- X termio_final(&termio, &chardata);
- X
- X /* Now the newline character should be properly written */
- X
- X (void) write(1, "\n", 1);
- X
- X /* Let /bin/login take care of password validation */
- X
- X (void) execl("/bin/login", "login", logname, (char *) 0);
- X error("%s: can't exec /bin/login", options.tty);
- X /* NOTREACHED */
- X}
- X
- X/* parse-args - parse command-line arguments */
- X
- Xparse_args(argc, argv, op)
- Xint argc;
- Xchar **argv;
- Xstruct options *op;
- X{
- X extern char *optarg; /* getopt */
- X extern int optind; /* getopt */
- X int c;
- X
- X while (isascii(c = getopt(argc, argv, "a:himt:"))) {
- X switch (c) {
- X case 'a': /* enable auto-baud feature */
- X parse_speeds(op, optarg);
- X break;
- X case 'h': /* do not hangup the tty */
- X op->flags &= ~F_HANGUP;
- X break;
- X case 'i': /* do not show /etc/issue */
- X op->flags &= ~F_ISSUE;
- X break;
- X case 'm': /* parse modem status message */
- X op->flags |= F_PARSE;
- X break;
- X case 't': /* time out */
- X if ((op->timeout = atoi(optarg)) <= 0)
- X error("bad timeout value: %s", optarg);
- X break;
- X case '?':
- X usage();
- X }
- X }
- X if (argc != optind + 2) /* check parameter count */
- X usage();
- X op->tty = argv[optind++]; /* tty name */
- X if ((op->speeds[0] = bcode(argv[optind])) <= 0) /* baud rate */
- X error("bad speed: %s", argv[optind]);
- X}
- X
- X/* parse_speeds - parse alternate baud rates */
- X
- Xparse_speeds(op, arg)
- Xstruct options *op;
- Xchar *arg;
- X{
- X char *strtok();
- X char *cp;
- X
- X for (cp = strtok(arg, ","); cp != 0; cp = strtok((char *) 0, ",")) {
- X if ((op->speeds[op->numspeed++] = bcode(cp)) <= 0)
- X error("bad speed: %s", cp);
- X if (op->numspeed > MAXSPEED)
- X error("too many alternate speeds");
- X }
- X}
- X
- X/* update_utmp - update our utmp entry */
- X
- Xupdate_utmp(line)
- Xchar *line;
- X{
- X struct utmp ut;
- X long ut_size = sizeof(ut); /* avoid nonsense */
- X int ut_fd;
- X int mypid = getpid();
- X long time();
- X long lseek();
- X char *strncpy();
- X
- X /*
- X * The utmp file holds miscellaneous information about things started by
- X * /etc/init and other system-related events. Our purpose is to update
- X * the utmp entry for the current process, in particular the process type
- X * and the tty line we are listening to. Return successfully only if the
- X * utmp file can be opened for update, and if we are able to find our
- X * entry in the utmp file.
- X */
- X
- X if ((ut_fd = open(UTMP_FILE, 2)) < 0) {
- X error("%s: open for update", UTMP_FILE);
- X } else {
- X while (read(ut_fd, (char *) &ut, sizeof(ut)) == sizeof(ut)) {
- X if (ut.ut_type == INIT_PROCESS && ut.ut_pid == mypid) {
- X ut.ut_type = LOGIN_PROCESS;
- X ut.ut_time = time((long *) 0);
- X (void) strncpy(ut.ut_name, "LOGIN", sizeof(ut.ut_name));
- X (void) strncpy(ut.ut_line, line, sizeof(ut.ut_line));
- X (void) lseek(ut_fd, -ut_size, 1);
- X (void) write(ut_fd, (char *) &ut, sizeof(ut));
- X (void) close(ut_fd);
- X return;
- X }
- X }
- X error("no utmp entry found for process id %u", mypid);
- X }
- X}
- X
- X/* open_tty - open tty as standard { input, output, error } */
- X
- Xopen_tty(tty, tp)
- Xchar *tty;
- Xstruct termio *tp;
- X{
- X struct stat st;
- X
- X /* Close standard { input, output, error } files, just in case */
- X
- X (void) close(0);
- X (void) close(1);
- X (void) close(2);
- X errno = 0; /* ignore above errors */
- X
- X /* Make sure we are given a character device */
- X
- X if (chdir("/dev"))
- X error("/dev: chdir() failed");
- X if (stat(tty, &st) < 0)
- X error("/dev/%s: stat() failed", tty);
- X if ((st.st_mode & S_IFMT) != S_IFCHR)
- X error("not a character device: /dev/%s", tty);
- X
- X /* Set up new standard input, output and error files */
- X
- X if (open(tty, 2) != 0) /* set up std input */
- X error("/dev/%s: cannot open as standard input", tty);
- X if (dup(0) != 1 || dup(0) != 2) /* set up std out and std err */
- X error("%s: dup problem", tty); /* we have a problem */
- X if (ioctl(0, TCGETA, tp) < 0) /* read tty status bits */
- X error("%s: ioctl failed", tty); /* this is not a terminal */
- X
- X /* It seems to be a terminal; set proper protections and ownership */
- X
- X (void) chown(tty, 0, 0); /* root, sys */
- X (void) chmod(tty, 0622); /* crw--w--w- */
- X errno = 0; /* ignore above errors */
- X}
- X
- X#ifdef lint
- X#define HANGUP
- X#endif
- X
- X/* hangup_tty - hang up by forcing DTR down for at least 2 seconds */
- X
- Xhangup_tty(tp)
- Xstruct termio *tp;
- X{
- X#ifdef HANGUP
- X (void) signal(SIGHUP, SIG_IGN);
- X tp->c_cflag &= ~CBAUD;
- X tp->c_cflag |= B0;
- X (void) ioctl(0, TCSETA, tp);
- X (void) signal(SIGHUP, SIG_DFL);
- X (void) sleep(2);
- X#endif
- X}
- X
- X/* termio_init - initialize termio settings */
- X
- Xtermio_init(tp, speed)
- Xstruct termio *tp;
- Xint speed;
- X{
- X
- X /*
- X * Initial termio settings: 8-bit characters, raw-mode, blocking i/o.
- X * Special characters are set after we have read the login name; all
- X * reads will be done in raw mode anyway.
- X */
- X
- X tp->c_cflag = CS8 | HUPCL | CREAD | speed;
- X tp->c_iflag = tp->c_lflag = tp->c_oflag = tp->c_line = 0;
- X tp->c_cc[VMIN] = 1;
- X tp->c_cc[VTIME] = 0;
- X (void) ioctl(0, TCSETA, tp);
- X}
- X
- X/* auto_baud - extract baud rate from modem status message */
- X
- Xauto_baud(tp)
- Xstruct termio *tp;
- X{
- X int speed;
- X int vmin;
- X int iflag;
- X char buf[BUFSIZ];
- X char *bp;
- X int nread;
- X
- X /*
- X * This works only if the modem produces its status code AFTER raising
- X * the DCD line, and if the computer is fast enough to set the proper
- X * baud rate before the message has gone by. We expect a message of the
- X * following format:
- X *
- X * <junk><number><junk>
- X *
- X * The number is interpreted as the baud rate of the incoming call. If the
- X * modem does not tell us the baud rate within one second we will keep
- X * using the current baud rate. It is advisable to enable baud-rate
- X * cycling (-a option) if the processing of modem status messages is
- X * enabled.
- X */
- X
- X /* Use 7-bit characters, don't block if input queue is empty */
- X
- X iflag = tp->c_iflag;
- X tp->c_iflag |= ISTRIP; /* enable 8th-bit stripping */
- X vmin = tp->c_cc[VMIN];
- X tp->c_cc[VMIN] = 0; /* don't block if queue empty */
- X (void) ioctl(0, TCSETA, tp);
- X
- X /*
- X * Wait for a while, then read everything the modem has said so far and
- X * try to extract the speed of the dial-in call.
- X */
- X
- X (void) sleep(1);
- X if ((nread = read(0, buf, sizeof(buf) - 1)) > 0) {
- X buf[nread] = '\0';
- X for (bp = buf; bp < buf + nread; bp++) {
- X if (isascii(*bp) && isdigit(*bp)) {
- X if (speed = bcode(bp)) {
- X tp->c_cflag &= ~CBAUD;
- X tp->c_cflag |= speed;
- X }
- X break;
- X }
- X }
- X }
- X /* Restore settings */
- X
- X tp->c_iflag = iflag;
- X tp->c_cc[VMIN] = vmin;
- X (void) ioctl(0, TCSETA, tp);
- X}
- X
- X/* do_prompt - show login prompt, optionally preceded by /etc/issue contents */
- X
- Xdo_prompt(op, tp)
- Xstruct options *op;
- Xstruct termio *tp;
- X{
- X#ifdef ISSUE
- X int fd;
- X int oflag;
- X int n;
- X char buf[BUFSIZ];
- X#endif
- X
- X write(1, "\r\n", 2); /* Start a new line */
- X#ifdef ISSUE /* Optional: show /etc/issue */
- X if ((op->flags & F_ISSUE) && (fd = open(ISSUE, 0)) >= 0) {
- X oflag = tp->c_oflag; /* Save current setting */
- X tp->c_oflag |= (ONLCR | OPOST); /* Map NL in output to CR-NL */
- X (void) ioctl(0, TCSETAW, tp);
- X while ((n = read(fd, buf, sizeof(buf))) > 0)
- X (void) write(1, buf, n);
- X tp->c_oflag = oflag; /* Restore settings */
- X (void) ioctl(0, TCSETAW, tp); /* Wait till output gone */
- X (void) close(fd);
- X }
- X#endif
- X (void) write(1, LOGIN, sizeof(LOGIN) - 1); /* Always show login prompt */
- X}
- X
- X/* next_speed - select next baud rate */
- X
- Xnext_speed(tp, op)
- Xstruct termio *tp;
- Xstruct options *op;
- X{
- X op->curspeed = (op->curspeed + 1) % op->numspeed;
- X tp->c_cflag &= ~CBAUD;
- X tp->c_cflag |= op->speeds[op->curspeed];
- X (void) ioctl(0, TCSETA, tp);
- X}
- X
- X/* get_logname - get user name, establish parity, speed, erase, kill, eol */
- X
- Xchar *get_logname(op, cp, tp)
- Xstruct options *op;
- Xstruct chardata *cp;
- Xstruct termio *tp;
- X{
- X char logname[BUFSIZ];
- X char *bp;
- X char c; /* input character, full eight bits */
- X char ascval; /* low 7 bits of input character */
- X int bits; /* # of "1" bits per character */
- X int mask; /* mask with 1 bit up */
- X static char *erase[] = { /* backspace-space-backspace */
- X "\010\040\010", /* space parity */
- X "\010\040\010", /* odd parity */
- X "\210\240\210", /* even parity */
- X "\210\240\210", /* no parity */
- X };
- X
- X /* Initialize kill, erase, parity etcetera (also after switching speeds) */
- X
- X cp->kill = DEF_KILL;
- X cp->erase = DEF_ERASE;
- X cp->parity = 0;
- X
- X /* Flush any pending input */
- X
- X (void) ioctl(0, TCFLSH, (struct termio *) 0);
- X
- X /* Read a login name */
- X
- X for (*logname = 0; *logname == 0; /* void */ ) {
- X
- X /* Write issue file and prompt, with "parity" bit == 0 */
- X
- X do_prompt(op, tp);
- X
- X /* Read name, watch for break, parity, erase, kill, end-of-line */
- X
- X for (bp = logname, cp->eol = 0; cp->eol == 0; /* void */ ) {
- X if (read(0, &c, 1) < 1)
- X error("%s: read error", op->tty);
- X
- X /* Do BREAK handling elsewhere */
- X
- X if ((c == 0) && op->numspeed > 1)
- X return (0);
- X
- X /* Do parity bit handling */
- X
- X if (c != (ascval = (c & 0177))) { /* "parity" bit on ? */
- X for (bits = 1, mask = 1; mask & 0177; mask <<= 1)
- X if (mask & ascval)
- X bits++; /* count "1" bits */
- X cp->parity |= ((bits & 1) ? 1 : 2);
- X }
- X /* Do erase, kill and end-of-line processing */
- X
- X switch (ascval) {
- X case CR:
- X case NL:
- X *bp = 0; /* terminate logname */
- X cp->eol = ascval; /* set end-of-line char */
- X break;
- X case BS:
- X case DEL:
- X case '#':
- X cp->erase = ascval; /* set erase character */
- X if (bp > logname) {
- X (void) write(1, erase[cp->parity], 3);
- X bp--;
- X }
- X break;
- X case CTL('U'):
- X case '@':
- X cp->kill = ascval; /* set kill character */
- X while (bp > logname) {
- X (void) write(1, erase[cp->parity], 3);
- X bp--;
- X }
- X break;
- X case CTL('D'):
- X exit(0);
- X default:
- X if (!isascii(ascval) || !isprint(ascval)) {
- X /* ignore garbage characters */ ;
- X } else if (bp - logname >= sizeof(logname) - 1) {
- X error("%s: input overrun", op->tty);
- X } else {
- X (void) write(1, &c, 1); /* echo the character */
- X *bp++ = ascval; /* and store it */
- X }
- X break;
- X }
- X }
- X }
- X cp->capslock = caps_lock(logname); /* upper case w/o lower case? */
- X return (logname);
- X}
- X
- X/* termio_final - set the final tty mode bits */
- X
- Xtermio_final(tp, cp)
- Xstruct termio *tp;
- Xstruct chardata *cp;
- X{
- X /* General terminal-independent stuff */
- X
- X tp->c_iflag |= IXON | IXOFF; /* 2-way flow control */
- X tp->c_lflag |= ICANON | ISIG | ECHO | ECHOE | ECHOK;
- X tp->c_oflag |= OPOST;
- X tp->c_cc[VEOF] = DEF_EOF;
- X tp->c_cc[VEOL] = DEF_EOL;
- X tp->c_cc[VINTR] = DEF_INTR;
- X tp->c_cc[VQUIT] = DEF_QUIT;
- X tp->c_cc[VKILL] = DEF_KILL;
- X tp->c_cc[VERASE] = DEF_ERASE;
- X tp->c_cc[VSWTCH] = DEF_SWITCH;
- X
- X /* Account for special characters seen in input */
- X
- X if (cp->eol == CR) {
- X tp->c_iflag |= ICRNL; /* map CR in input to NL */
- X tp->c_oflag |= ONLCR; /* map NL in output to CR-NL */
- X }
- X tp->c_cc[VERASE] = cp->erase; /* set erase character */
- X tp->c_cc[VKILL] = cp->kill; /* set kill character */
- X
- X /* Account for the presence or absence of parity bits in input */
- X
- X switch (cp->parity) {
- X case 0: /* space (always 0) parity */
- X break;
- X case 1: /* odd parity */
- X tp->c_cflag |= PARODD;
- X /* FALLTHROUGH */
- X case 2: /* even parity */
- X tp->c_cflag |= PARENB;
- X tp->c_iflag |= INPCK | ISTRIP;
- X /* FALLTHROUGH */
- X case (1 | 2): /* no parity bit */
- X tp->c_cflag &= ~CSIZE;
- X tp->c_cflag |= CS7;
- X break;
- X }
- X /* Account for upper case without lower case */
- X
- X if (cp->capslock) {
- X tp->c_iflag |= IUCLC;
- X tp->c_lflag |= XCASE;
- X tp->c_oflag |= OLCUC;
- X }
- X /* Finally, make the new settings effective */
- X
- X (void) ioctl(0, TCSETA, tp);
- X}
- X
- X/* caps_lock - string contains upper case without lower case */
- X
- Xcaps_lock(s)
- Xchar *s;
- X{
- X int hascaps;
- X
- X for (hascaps = 0; *s; s++) {
- X if (islower(*s))
- X return (0);
- X if (hascaps == 0)
- X hascaps = isupper(*s);
- X }
- X return (hascaps);
- X}
- X
- X/* bcode - convert speed string to speed code; return 0 on failure */
- X
- Xbcode(s)
- Xchar *s;
- X{
- X struct Speedtab {
- X int speed;
- X int code;
- X };
- X static struct Speedtab speedtab[] = {
- X 50, B50,
- X 75, B75,
- X 110, B110,
- X 134, B134,
- X 150, B150,
- X 200, B200,
- X 300, B300,
- X 600, B600,
- X 1200, B1200,
- X 1800, B1800,
- X 2400, B2400,
- X 4800, B4800,
- X 9600, B9600,
- X 19200, EXTA,
- X 0, 0,
- X };
- X struct Speedtab *sp;
- X int speed = atoi(s);
- X
- X for (sp = speedtab; sp->speed; sp++)
- X if (sp->speed == speed)
- X return (sp->code);
- X return (0);
- X}
- X
- X/* usage - explain */
- X
- Xusage()
- X{
- X static char args[] =
- X "[-a alternate_rates] [-h] [-i] [-m] [-t timeout] line baud_rate";
- X
- X error("usage: %s %s", progname, args);
- X}
- X
- X/* error - report errors to the console; only understands %s */
- X
- X#define str2cpy(b,s1,s2) strcat(strcpy(b,s1),s2)
- X
- X/* VARARGS */
- X
- Xerror(va_alist)
- Xva_dcl
- X{
- X va_list ap;
- X char *fmt;
- X int fd;
- X int err = errno;
- X char buf[BUFSIZ];
- X char *bp;
- X
- X if ((fd = open("/dev/console", 1)) >= 0) {
- X (void) str2cpy(buf, progname, ": ");
- X bp = buf + strlen(buf);
- X
- X /*
- X * %s expansion is done by hand. The program would become three times
- X * as big if we would use the stdio library...
- X */
- X
- X va_start(ap);
- X fmt = va_arg(ap, char *);
- X while (*fmt) {
- X if (strncmp(fmt, "%s", 2) == 0) {
- X (void) strcat(bp, va_arg(ap, char *));
- X bp += strlen(bp);
- X fmt += 2;
- X } else {
- X *bp++ = *fmt++;
- X }
- X }
- X *bp = 0;
- X va_end(ap);
- X
- X /* Add system error message if errno was set */
- X
- X if (err)
- X (void) str2cpy(bp, ": ", sys_errlist[errno]);
- X
- X /* Terminate with CR-LF since the console mode is unknown */
- X
- X (void) strcat(bp, "\r\n");
- X (void) write(fd, buf, strlen(buf));
- X (void) close(fd);
- X }
- X (void) sleep(5); /* be kind to init */
- X exit(1);
- X}
- END_OF_FILE
- if test 22691 -ne `wc -c <'agetty.c'`; then
- echo shar: \"'agetty.c'\" unpacked with wrong size!
- fi
- # end of 'agetty.c'
- fi
- if test -f 'agetty.8' -a "${1}" != "-c" ; then
- echo shar: Will not clobber existing file \"'agetty.8'\"
- else
- echo shar: Extracting \"'agetty.8'\" \(3984 characters\)
- sed "s/^X//" >'agetty.8' <<'END_OF_FILE'
- X.TH AGETTY 8
- X.ad
- X.fi
- X.SH NAME
- Xagetty
- X\-
- Xalternative System-V getty for dial-up lines
- X.SH SYNOPSIS
- X.na
- X.nf
- Xagetty [-a alternate_rates] [-h] [-i] [-m] [-t timeout] port baud_rate
- X.SH DESCRIPTION
- X.ad
- X.fi
- X\fIagetty\fR opens a tty port, prompts for a login name and invokes the
- X/bin/login command. It is normally invoked by \fIinit(8)\fR.
- X
- X\fIagetty\fR has some useful features for dial-up lines that are
- Xnot present in the System V Release 2 getty command:
- X.IP o
- XAdapts the tty settings to parity bits and to
- Xerase, kill and end-of-line characters found in its input. The
- Xprogram understands 7-bit characters with even, odd, none or space
- Xparity, and 8-bit characters with no parity. The following special
- Xcharacters are recognized: @ and Control-U (kill); #, DEL and
- Xback space (erase); carriage return and line feed (end of line).
- X.IP o
- XOptionally recognizes the baud rate of incoming calls from the
- Xstatus messages produced by some multi-speed Hayes-compatible modems.
- X.IP o
- XOptionally does not display the contents of the \fI/etc/issue\fR file.
- X.PP
- XThis program does not use the \fI/etc/gettydefs\fR file. Except for
- Xdifferences described in the documentation, the program appears to
- Xoperate similar to the System-V Release 2 \fIgetty\fR program.
- X
- XOptions:
- X.TP
- X-a alternate_rates
- XInitially the program will use the \fIbaud_rate\fR as specified.
- XUpon receipt of successive BREAK characters the program will step
- Xthrough the \fIalternate_rates\fR, which should be specified as a
- Xcomma-separated list (preferably in decreasing order). After all
- X\fIalternate_rates\fR have been tried, \fIagetty\fR will try the
- Xspeed specified with the \fIbaud_rate\fR argument and so on.
- X.TP
- X-h
- XDo not hang up the line. Normally, \fIagetty\fR will lower
- XDTR for two seconds to force a modem to hang up (if the hangup
- Xfeature has been compiled into the program).
- X.TP
- X-i
- XDo not display the contents of \fI/etc/issue\fR before writing the
- Xlogin prompt. Terminals or computer programs may become confused
- Xwhen receiving lots of text at the wrong baud rate; dial-up scripts
- Xmay fail if the login prompt is preceded by too much text.
- X.TP
- X-m
- XTry to extract the baud rate of incoming calls from the status message
- Xproduced by some multi-speed Hayes-compatible modems. These usually
- Xproduce a status message of the form: "<junk><speed><junk>".
- XIf no \fIspeed\fR is found within one second, the \fIbaud_rate\fR as
- Xspecified on the command line will be used. Since the \fI-m\fR feature
- Xwill work only on lightly-loaded systems, you will probably want to use
- Xit in combination with the \fI-a\fR option.
- X.TP
- X-t timeout
- XCauses the program to terminate if no user name could be read
- Xwithin \fItimeout\fR seconds. This is useful only for dial-in lines.
- X.SH EXAMPLES
- X.na
- X.nf
- XFor hard-wired lines:
- X.ti +5
- X/etc/agetty ttyM0 9600
- X
- XFor dial-in lines with a 300/1200/2400 baud multi-speed modem:
- X.ti +5
- X/etc/agetty -t60 -m -a1200,300 ttyM1 2400
- X.SH FILES
- X.na
- X.nf
- X/etc/utmp, the system log file.
- X/etc/issue, printed before the login prompt.
- X/dev/console, problem reports.
- X.SH BUGS
- X.ad
- X.fi
- XThe baud-rate detection code (the \fI-m\fR option) only works if
- X\fIagetty\fR is scheduled soon enough after completion of a dial-in
- Xcall (within 30 ms with modems that talk at 2400 baud). For robustness,
- Xalways use the \fI-m\fR option in combination with the \fI-a\fR option.
- X
- XThe contents of the /etc/issue file and the login prompt are always
- Xoutput with space parity.
- X.SH DIAGNOSTICS
- X.ad
- X.fi
- XAll diagnostics are written to the console device. Error messages are
- Xproduced if the \fIport\fR argument does not specify a terminal; if
- Xthere is no /etc/utmp entry for the current process; and so on.
- X.SH AUTHOR(S)
- X.na
- X.nf
- XW.Z. Venema <wietse@wzv.win.tue.nl>
- XEindhoven University of Technology
- XDepartment of Mathematics and Computer Science
- XDen Dolech 2, P.O. Box 513, 5600 MB Eindhoven, The Netherlands
- X.SH CREATION DATE
- X.na
- X.nf
- XSat Nov 25 22:51:05 MET 1989
- X.SH LAST MODIFICATION
- X.na
- X.nf
- X90/01/28 17:53:06
- X.SH VERSION/RELEASE
- X.na
- X.nf
- X1.26
- END_OF_FILE
- if test 3984 -ne `wc -c <'agetty.8'`; then
- echo shar: \"'agetty.8'\" unpacked with wrong size!
- fi
- # end of 'agetty.8'
- fi
- if test -f 'Makefile' -a "${1}" != "-c" ; then
- echo shar: Will not clobber existing file \"'Makefile'\"
- else
- echo shar: Extracting \"'Makefile'\" \(257 characters\)
- sed "s/^X//" >'Makefile' <<'END_OF_FILE'
- X# @(#) Makefile 1.3 11/26/89 22:20:28
- X
- XSHELL = /bin/sh
- XCFLAGS = -s -O
- XFILES = README agetty.c agetty.8 Makefile
- X
- Xagetty: agetty.c
- X cc $(CFLAGS) -o $@ $?
- X
- Xclean:
- X rm -f agetty.o agetty
- X
- Xshar: $(FILES)
- X @shar $(FILES)
- X
- Xagetty.8:
- X srctoman agetty.c >agetty.8
- END_OF_FILE
- if test 257 -ne `wc -c <'Makefile'`; then
- echo shar: \"'Makefile'\" unpacked with wrong size!
- fi
- # end of 'Makefile'
- fi
- echo shar: End of shell archive.
- exit 0
-
-